﻿#region Copyright (c) 2003 - 2008, Andreas Mueller
/////////////////////////////////////////////////////////////////////////////////////////
// 
// Copyright (c) 2003 - 2008, Andreas Mueller.
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// which accompanies this distribution, and is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// Contributors:
//    Andreas Mueller - initial API and implementation
//
// 
// This software is derived from software bearing the following
// restrictions:
// 
// Copyright (c) 1994
// Hewlett-Packard Company
// 
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation.  Hewlett-Packard Company makes no
// representations about the suitability of this software for any
// purpose.  It is provided "as is" without express or implied warranty.
// 
// 
// Copyright (c) 1996,1997
// Silicon Graphics Computer Systems, Inc.
// 
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation.  Silicon Graphics makes no
// representations about the suitability of this software for any
// purpose.  It is provided "as is" without express or implied warranty.
// 
// 
// (C) Copyright Nicolai M. Josuttis 1999.
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
// 
/////////////////////////////////////////////////////////////////////////////////////////
#endregion


using NStl.Linq;
using NUnit.Framework;
using NStl.Collections;
using NUnit.Framework.SyntaxHelpers;
using System.Collections;
using System;
using NStl.Exceptions;

namespace NStl.NUnit.ContainerFixture.Deque
{
    [TestFixture]
    public class DequeFixture
    {   
        [Test]
        public void Clear()
        {
            Deque<int> deque = new Deque<int>();
            FillDeque(deque, 30);

            Assert.That(deque.Count, Is.EqualTo(30));

            deque.Clear();
            Assert.That(deque, Is.Empty);
            Assert.That(deque.Count, Is.EqualTo(0));

            FillDeque(deque, 25);
            Assert.That(deque, Is.Not.Empty);
            Assert.That(deque.Count, Is.EqualTo(25));
        }
        private static void FillDeque(Deque<int> d, int count)
        {
            for(int i = 0; i < count; ++i)
                if(i%2 == 0)
                    d.PushBack(i);
                else
                    d.PushFront(i);
        }
        [Test]
        public void ReverseItarators()
        {
            int[] expected = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            Deque<int> deque = new Deque<int>(expected);

            Array.Reverse(expected);

            ICollection reverted = deque.RBegin().AsCollection(deque.REnd());
            //ArrayList tmp = new ArrayList(reverted);
            Assert.That(reverted, Is.EqualTo(expected));
        }
        [Test]
        public void Empty()
        {
            Deque<int> d = new Deque<int>();
            Assert.IsTrue(d.Empty);

            d.PushBack(1);
            Assert.IsFalse(d.Empty);

            d.Clear();
            Assert.IsTrue(d.Empty);
        }
        [Test]
        public void Indexer()
        {
            Deque<int> d = new Deque<int>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);

            for (int i = 0; i < d.Count; ++i)
                Assert.That(d[i], Is.EqualTo(i));
        }

        [Test]
        [ExpectedException(typeof(ArgumentOutOfRangeException))]
        public void IndexerWithIndexBelow0()
        {
            Deque<int> d = new Deque<int>(0, 1, 2);

            int notUsed = d[-1];
            NeverCalled(notUsed);
        }

        [Test]
        [ExpectedException(typeof(ArgumentOutOfRangeException))]
        public void IndexerWithIndexBehindEnd()
        {
            Deque<int> d = new Deque<int>(0, 1, 2);

            NeverCalled(d[d.Count]);
        }
        [Test]
        public void Front()
        {
            Deque<int> d = new Deque<int>();
            d.PushBack(1);

            Assert.AreEqual(1, d.Front());
        }

        [Test]
        [ExpectedException(typeof(ContainerEmptyException))]
        public void FrontOnEmptyContainer()
        {
            Deque<int> d = new Deque<int>();
            NeverCalled(d.Front());
        }
        private static void NeverCalled(object o)
        {
            NeverCalled(o);
        }
        [Test]
        public void Back()
        {
            Deque<int> d = new Deque<int>();
            d.PushBack(1);

            Assert.AreEqual(1, d.Back());
        }

        [Test]
        [ExpectedException(typeof(ContainerEmptyException))]
        public void BackOnEmptyContainer()
        {
            Deque<int> d = new Deque<int>();
            NeverCalled(d.Back());
        }

        [Test]
        public void PopBack()
        {
            ICollection expected = new[] { 0, 1, 2 };
            Deque<int> d = new Deque<int>(0, 1, 2, 3);
            d.PopBack();

            Assert.That(d, Is.EqualTo(expected));
        }
        [Test]
        [ExpectedException(typeof(ContainerEmptyException))]
        public void PopBackOnEmptyContainer()
        {
            Deque<int> d = new Deque<int>();
            d.PopBack();
        }
        [Test]
        public void PopFront()
        {
            ICollection expected = new[] {1, 2, 3};
            Deque<int> d = new Deque<int>(0, 1, 2, 3);
            d.PopFront();

            Assert.That(d, Is.EqualTo(expected));
        }
        [Test]
        [ExpectedException(typeof(ContainerEmptyException))]
        public void PopFrontOnEmptyContainer()
        {
            Deque<int> d = new Deque<int>();
            d.PopFront();
        }

        [Test]
        public void Swap()
        {
            ICollection expected1 = new[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
            ICollection expected2 = new[] { 0, -1, -2, -3, -4, -5, -6, -7, -8, -9 };
            Deque<int> d1 = new Deque<int>(expected1);
            Deque<int> d2 = new Deque<int>(expected2);

            d1.Swap(d2);

            Assert.That(expected1, Is.EqualTo(d2));
            Assert.That(expected2, Is.EqualTo(d1));
        }

        [Test]
        public void BackInserter()
        {
            ICollection expected = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            Deque<int> d = new Deque<int>();
            Algorithm.Copy(expected.Begin<int>(), expected.End<int>(), d.AddLastInserter());

            Assert.That(d, Is.EqualTo(expected));
        }
        [Test]
        public void FrontInserter()
        {
            ArrayList expected = new ArrayList{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            Deque<int> d = new Deque<int>();
            Algorithm.Copy(expected.Begin<int>(), expected.End<int>(), d.AddFirstInserter());

            expected.Reverse();
            Assert.That(d, Is.EqualTo(expected));
        }

        [Test]
        public void MiddleInserter()
        {

            ICollection toInsert = new[] {42, 43, 44, 45};
            Deque<int> d = new Deque<int>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
            Algorithm.Copy(toInsert.Begin<int>(), toInsert.End<int>(), d.InsertIterator(d.Begin() + 2));

            ICollection expected = new[] {0, 1, 45, 44, 43, 42, 2, 3, 4, 5, 6, 7, 8, 9};

            Assert.That(d, Is.EqualTo(expected));
        }
    }
}
